package studio.baka.satoripixeldungeon.actors.mobs;

import studio.baka.satoripixeldungeon.Dungeon;
import studio.baka.satoripixeldungeon.actors.Actor;
import studio.baka.satoripixeldungeon.actors.Char;
import studio.baka.satoripixeldungeon.actors.buffs.Amok;
import studio.baka.satoripixeldungeon.actors.buffs.Corruption;
import studio.baka.satoripixeldungeon.actors.buffs.Poison;
import studio.baka.satoripixeldungeon.messages.Messages;
import studio.baka.satoripixeldungeon.sprites.BeeSprite;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;

import java.util.HashSet;

//FIXME the AI for these things is becoming a complete mess, should refactor
public class Bee extends Mob {

    {
        spriteClass = BeeSprite.class;

        viewDistance = 4;

        EXP = 0;

        flying = true;
        state = WANDERING;

        //only applicable when the bee is charmed with elixir of honeyed healing
        intelligentAlly = true;
    }

    private int level;

    //-1 refers to a pot that has gone missing.
    private int potPos;
    //-1 for no owner
    private int potHolder;

    private static final String LEVEL = "level";
    private static final String POTPOS = "potpos";
    private static final String POTHOLDER = "potholder";
    private static final String ALIGMNENT = "alignment";

    @Override
    public void storeInBundle(Bundle bundle) {
        super.storeInBundle(bundle);
        bundle.put(LEVEL, level);
        bundle.put(POTPOS, potPos);
        bundle.put(POTHOLDER, potHolder);
        bundle.put(ALIGMNENT, alignment);
    }

    @Override
    public void restoreFromBundle(Bundle bundle) {
        super.restoreFromBundle(bundle);
        spawn(bundle.getInt(LEVEL));
        potPos = bundle.getInt(POTPOS);
        potHolder = bundle.getInt(POTHOLDER);
        if (bundle.contains(ALIGMNENT)) alignment = bundle.getEnum(ALIGMNENT, Alignment.class);
    }

    public void spawn(int level) {
        this.level = level;

        HT = (2 + level) * 4;
        defenseSkill = 9 + level;
    }

    public void setPotInfo(int potPos, Char potHolder) {
        this.potPos = potPos;
        if (potHolder == null)
            this.potHolder = -1;
        else
            this.potHolder = potHolder.id();
    }

    public int potPos() {
        return potPos;
    }

    public int potHolderID() {
        return potHolder;
    }

    @Override
    public int attackSkill(Char target) {
        return defenseSkill;
    }

    @Override
    public int damageRoll() {
        return Random.NormalIntRange(HT / 10, HT / 4);
    }

    @Override
    public int attackProc(Char enemy, int damage) {
        damage = super.attackProc(enemy, damage);
        if (enemy instanceof Mob) {
            ((Mob) enemy).aggro(this);
        }
        return damage;
    }

    @Override
    protected Char chooseEnemy() {
        //if the pot is no longer present, default to regular AI behaviour
        if (alignment == Alignment.ALLY || (potHolder == -1 && potPos == -1)) {
            return super.chooseEnemy();

            //if something is holding the pot, target that
        } else if (Actor.findById(potHolder) != null) {
            return (Char) Actor.findById(potHolder);

            //if the pot is on the ground
        } else {

            //try to find a new enemy in these circumstances
            if (enemy == null || !enemy.isAlive() || state == WANDERING
                    || Dungeon.level.distance(enemy.pos, potPos) > 3
                    || (alignment == Alignment.ALLY && enemy.alignment == Alignment.ALLY)) {

                //find all mobs near the pot
                HashSet<Char> enemies = new HashSet<>();
                for (Mob mob : Dungeon.level.mobs) {
                    if (!(mob == this)
                            && Dungeon.level.distance(mob.pos, potPos) <= 3
                            && mob.alignment != Alignment.NEUTRAL
                            && !(alignment == Alignment.ALLY && mob.alignment == Alignment.ALLY)) {
                        enemies.add(mob);
                    }
                }

                if (!enemies.isEmpty()) {
                    return Random.element(enemies);
                } else {
                    if (alignment != Alignment.ALLY && Dungeon.level.distance(Dungeon.hero.pos, potPos) <= 3) {
                        return Dungeon.hero;
                    } else {
                        return null;
                    }
                }

            } else {
                return enemy;
            }


        }
    }

    @Override
    protected boolean getCloser(int target) {
        if (alignment == Alignment.ALLY && enemy == null && buff(Corruption.class) == null) {
            target = Dungeon.hero.pos;
        } else if (enemy != null && Actor.findById(potHolder) == enemy) {
            target = enemy.pos;
        } else if (potPos != -1 && (state == WANDERING || Dungeon.level.distance(target, potPos) > 3))
            this.target = target = potPos;
        return super.getCloser(target);
    }

    @Override
    public String description() {
        if (alignment == Alignment.ALLY && buff(Corruption.class) == null) {
            return Messages.get(this, "desc_honey");
        } else {
            return super.description();
        }
    }

    {
        immunities.add(Poison.class);
        immunities.add(Amok.class);
    }
}